<?php
/* --------------------------------
 *  Ядро
 *
 * 9 августа 2012
 * © Deemon
 --------------------------------*/
require('cfg.main.php');
require('DBConnector/mysql.php');
date_default_timezone_set(TIME_ZONE);//Формат даты



	function startArchive( $zipPath, $file, $localname )
	{
		global $elog;
		$zip = new ZipArchive();

		if( $zip->open($zipPath, ZIPARCHIVE::CREATE ) !== TRUE ) {
			$elog->add( 'Невозможно открыть архив: '.$zipPath );
		}
		else {
			$zip->addFile( $file, $localname );
			$zip->close();
		}
	}

	function getUDate($str_date,$day=true)  // Количество Юникс дней
	{
		$date_elems = explode(" ",$str_date);
		$date = explode("-", $date_elems[0]);
		$time = explode(":", $date_elems[1]);
		$res = mktime( $time[0], $time[1],$time[2], $date[1],$date[2], $date[0] );
		return( ( $day )? ($res/86400) : $res );
	}

	function getImageThumbUrl($url,$size=1)  // Модифицировать ссылку для получения миниатюры нужного размера
	{
		return $url;
	}

	function getJSArr($arr)  // php массив преобразовать к виду js массива
	{
		$res='';
		$end = count( (array)$arr ) - 1;
		$count = 0;
		foreach( $arr as $i => $val )
		{
			if(is_bool($val))
				$val=$val?'1':'0';
			elseif(is_array($val) || is_object($val))
				$val=getJSArr($val);
			else
			{
				$val=str_replace(array("\t",'\'',"\r\n","\n","\r"),array('','\\\'','\n','\n','\n'),$val);
				$val=is_numeric($val)?$val:'\''.$val.'\'';
			}
			$i=is_numeric($i)?$i:'\''.$i.'\'';
			$res.="$i:$val";
			if($count++!=$end)
				$res.=',';
		}
		return '{'.$res.'}';
	}

//Строку идентификаторов в массив
	function getIdsArr($str,$d='#')
	{
		$str=preg_replace(array('@^'.$d.'@','@'.$d.'$@'),'',$str);
		return ($str=='')?array(): explode($d.$d,$str);
	}
//Числовой массив в строку
	function getIdsStr($arr,$d='#')
	{
		if($arr)
		{
			sort($arr);
			$str=implode($d.$d,array_unique(array_diff($arr,array(''))));
			return ($str=='' ? '' : $d.$str.$d);
		}
		return '';

	}

//Перенаправление страницы после удачного выполнения запроса
	function successRedirect($params=array())
	{
			$GLOBALS['elog']->add($params);
		//В куки
		if(isset($params['cookie_message']))
			setcookie('cookie_message',serialize($params['cookie_message']),time()+120);
		//В сессию
		if(isset($params['message']))
			$_SESSION['session_message']['text']=$params['message'];
		header('Location: '.(isset($params['url'])?$params['url']:$_SERVER['REQUEST_URI']));
		exit();
	}

//Безопасный запуск сессии
	function sessionStart()
	{
		static $session=false;
		if(!$session)
		{
			$GLOBALS['elog']->add('Сессия запущена',DEE_NOTICE);
			$session=session_start();
		}
	}

//Кодирование и декодирование строки
	function encode($String,$decode=false,$pass=false)
	{
		if($decode)$String=urldecode($String);
		$Salt=defined(ENCODE_SALT)?ENCODE_SALT:'9q8SkQorolAMp'; //"соль"
		$StrLen = strlen($String);
		$Gamma = '';
		if(!$pass)$pass=ENCODE_PASS;
		while (strlen($Gamma)<$StrLen)
		{
			$Seq = pack("H*",sha1($Gamma.$pass.$Salt));
			$Gamma.=substr($Seq,0,8);
		}
	   return ($decode)? $String^$Gamma : urlencode ($String^$Gamma);
	}

	function isMobile()  //Пользователь зашел с мобильного ?
	{
		$agent = $_SERVER['HTTP_USER_AGENT'];
		static $mobile = array('Opera Mobi','Opera Mini','iPhone OS','Android','Smartphone','MOTOZINE','Symbian OS','IEMobile','WindowsMobile','WAP','nokia','Nokia.*/','SonyEricsson.+/','SAMSUNG-.+/','RoverPC','HTC_.+/','iPhone','iPod','MOT-.+/','Lenovo_.+/','LG-.+/','HTC_','BlackBerry.+/');
		foreach( $mobile as $val )
			if( preg_match( "#$val#i", $agent, $version ) )
				return $val;
		return false;
	}

	function getTranslit( $str )  // Русский текст на латиницу
	{
		static $translitArr = array(
		'а'=>'a','б'=>'b','в'=>'v','г'=>'g','д'=>'d','е'=>'e','ё'=>'e','ж'=>'j','з'=>'z','и'=>'i','й'=>'y','к'=>'k','л'=>'l','м'=>'m','н'=>'n','о'=>'o','п'=>'p','р'=>'r','с'=>'s','т'=>'t','у'=>'u','ф'=>'f','х'=>'h','ц'=>'c','ч'=>'ch','ш'=>'sh','щ'=>'shh','ъ'=>'','ы'=>'y','ь'=>'','э'=>'e','ю'=>'yu','я'=>'ya',
		'А'=>'A','Б'=>'B','В'=>'V','Г'=>'G','Д'=>'D','Е'=>'E','Ё'=>'E','Ж'=>'J','З'=>'Z','И'=>'I','Й'=>'Y','К'=>'K','Л'=>'L','М'=>'M','Н'=>'N','О'=>'O','П'=>'P','Р'=>'R','С'=>'S','Т'=>'T','У'=>'U','Ф'=>'F','Х'=>'H','Ц'=>'C','Ч'=>'CH','Ш'=>'SH','Щ'=>'SHH','Ъ'=>'','Ы'=>'Y','Ь'=>'','Э'=>'E','Ю'=>'Yu','Я'=>'Ya','№'=>'#'
		);
		return  strtr( $str, $translitArr );
	}

	function getRndStr( $len = 13 )  // Хеш-стока
	{
		$str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
		$code = '';
		$cl = strlen($str) - 1;
		for( $i=0; $i < $len; $i++ )
		{
			$code .= $str[mt_rand(0,$cl)];
		}
		return $code;
	}

	function saveGetPart()  // Вывод <input type="hidden" name="" /> чтобы сохранить GET часть текущего запроса
	{
		$res='';
		foreach( $_GET as $i => $val )
		{
			$res.='<input type="hidden" name="'.$i.'" value="'.$val.'" />';
		}
		return $res;
	}

	function getGoodUrl( $str, $replace = '-' )  // Преобразование строки в правильную ссылку
	{
		return preg_replace(  //удаляю точки и тире с конца, заменяю пробелы и слеш на тире и удаляю все кроме слов букв
			array('#[^-_\w\d\s/]+#','#[-_\s/]+#','#[-\._]+$#'),
			array( '' ,$replace, '' ),
			strtolower(trim(getTranslit($str))));
	}

	function getPagination( $obj_count, $limit, $one_side_links_count, $params = array() )  // Массив ссылок пагинации
	{
			//Общее количество ссылок
		$links_count = $one_side_links_count*2+1;
			//Количество страниц
		$pages_count = ($obj_count) ? ceil( $obj_count/$limit ): 0 ;
			//Массив ссылок
		$links_arr = array();
			//Текст ссылки перед номером страницы
		$url_before = isset( $params['url_before'] ) ? $params['url_before'] : '';
			//Текст ссылки после номера страницы
		$url_after = isset( $params['url_after'] ) ? $params['url_after'] : '';
			//Нужны ли ссылки на следущую, предыдущую страницы
		$next_prev_links = isset( $params['next_prev_links'] ) ? isset( $params['next_prev_links'] ) : true;
			//Нужны ли ссылки на первую и последнюю страницы
		$first_last_links = isset( $params['first_last_links'] ) ? isset( $params['first_last_links'] ) : false;
			//Приставка пагинации
		$q = false;
			//Индекс текущей страницы
		$current_index = 0;
			//Номер текущей страницы
		$curr_num = 1;
		//Пагинация через GET параметр
		if( isset( $params['pagination_get'] ) )
		{
			if(isset($_GET[$params['pagination_get']]))
				$curr_num=$_GET[$params['pagination_get']];
			$q=$params['pagination_get'].'=';
		}
		//Пагинация через доп url
		if(isset($params['pagination_url']))
		{
			if(preg_match('#'.$params['pagination_url'].'(\d+)#',$_SERVER['REQUEST_URI'],$res))
				$curr_num=$res[1];
			$q=$params['pagination_url'];
		}
		if($curr_num>0&&$curr_num<=$pages_count)
				$current_index=$curr_num-1;
		if($pages_count>1)
		{
			//всех страниц меньше чем нужно ссылок
			if($pages_count<=$links_count)
				for($i=0;$i<$pages_count;$i++)
					$links_arr[($i+1)]=($current_index==$i)
						?$links_arr[$i+1]=false
						:$url_before.(($i==0)?'':$q.($i+1)).$url_after;
			else
			{
				//Ближайшие ссылки слева
				if($current_index+1>$one_side_links_count)
					for($i=$current_index-$one_side_links_count;$i<$current_index;$i++)
						$links_arr[$i+1]=$url_before.(($i==0)?'':$q.($i+1)).$url_after;
				else
					for($i=0;$i<$current_index;$i++)
						$links_arr[$i+1]=$url_before.(($i==0)?'':$q.($i+1)).$url_after;
				//Текущая страница
				$links_arr[$current_index+1]=false;
				//Ближайшие ссылки справа
				if($pages_count>$current_index+1)
				{
					if($pages_count>$current_index+$one_side_links_count)
						for($i=$current_index+1;$i<$current_index+1+$one_side_links_count;$i++)
							$links_arr[$i+1]=$url_before.$q.($i+1).$url_after;
					else
						for($i=$current_index+1;$i<$pages_count;$i++)
							$links_arr[$i+1]=$url_before.$q.($i+1).$url_after;
				}
				//Предыдущая, следующая
				if($first_last_links)
				{
					//Если нет ссылки на первую страницу и текущая страница не первая
					$links_arr['first']=($current_index >$one_side_links_count && $current_index!=0)
						?$url_before.$url_after
						:false;
					//Если нет ссылки на последнюю страницу
					$links_arr['last']=($current_index+1<$pages_count-$one_side_links_count)
						?array('link'=>$url_before.$q.$pages_count.$url_after,'num'=>$pages_count)
						:false;
				}
			}
			//Предыдущая, следующая
			if($next_prev_links)
			{
				//Предыдущая страница
				if ($current_index != 0)
					$links_arr['prev']=$url_before.(($current_index==1)?'':"$q$current_index").$url_after;

				if ($current_index+1 <$pages_count) //Следующая страница
					$links_arr['next']=$url_before.$q.($current_index+2).$url_after;
			}
		}
		//Ссылка на первую страницу в случае если не верна указан номер страницы
		elseif($curr_num!=1) $links_arr[1]=$url_before.$q.(1).$url_after;
		return $links_arr;
	}

	class Elog  //Класс системных сообщений
	{
		private $elog_arr = array();  //Системные извещения
		public $to_write = array( DEE_TEST, DEE_ARR, DEE_NOTICE, DEE_ERROR, DEE_MESSAGE );

		function add( $text, $type = false, $params = array() )  //Добавить  в лог
		{
			if( !$type ) $type = DEE_TEST;
			$this->elog_arr[] = array(
									'text'	=> $text,
									'type'	=> $type,
									'params' => $params
								);
		}

		function getLog()  //Вывести лог
		{
			$res='';
			if( $this->to_write && $this->elog_arr )
			{
				$res.= '<ul class="elog">';
				foreach( $this->elog_arr as $i => $val )
				{
					if( in_array( $val['type'], $this->to_write ) )
					{
						$data='';
						$class = ( isset( $val['params']['class'] ) ? $val['params']['class'].' ' : '' ).$val['type'];

						if( is_array( $val['text'] ) || is_object( $val['text'] ) )
						{
							$data = print_r( $val['text'], true );
							$class.=' arr';
						}
						elseif( is_bool( $val['text'] ) )
						{
							$data = $val['text'] ? 'TRUE' : 'FALSE';
						}
						else
						{
							$data = $val['text'];
						}
						$res.= '<li class="'.$class.'">'
							.$data
						."</li>\r\n";
					}
				}
				$res.='</ul>';
			}
			return $res;
		}
	}

	abstract class Elog_use
	{
		public $elog = false;
		protected function add_log( $mess, $type = false, $params = array() )
		{
			$params['class'] = get_class( $this );
			if( $this->elog )
				$this->elog->add( $mess, $type, $params );
		}
	}

	class User extends Elog_use  //Класс пользователя
	{
		public $id=0;//Уникальный идентификатор пользователя
		public $name=false;//Имя
		public $email=false;//Электронная почта
		public $password=false;//Пароль в md5 кодировке
		public $group_name=false;//Название группы
		public $group_name_sys=false;//Системное название группы
		public $group_id=false;//Идентификатор группы
		public $date_last_visit=false;//Дата последнего визита
		public $date_reg=false;//Дата регистрации
		public $the_god_mode=false;//Полный доступ

		protected $permissions_obj=false;//Список разрешений пользователя
		protected $datas=false;//Дополнительные данные пользователя
		protected $permissions_arr=false;//Список разрешений пользователя
		protected $conn=false;//Cоединение с базой
		public $cache=false;//Работа с кешем


		public function User(&$conn)  //Конструктор
		{
			$this->conn=&$conn;
		}

		private function getEmpty()  //Очистка объекта
		{
			foreach( $this as $i => $val )
			{
				if( $i != 'conn' && $i != 'cache' && $i != 'elog' )
					$this->$i = false;
			}
			$this->id = 0;
		}

		public function allowed( $group_name, $field_name, $val_sys = false )  //Проверка разрешения для пользователя
		{
			//Главный администратор - полный доступ
			if($this->the_god_mode)return true;
			//Если пользователь не авторизован
			if(!$this->id)return false;
			if(!$this->permissions_obj)
			{
				$this->conn->query("select convert(group_concat(id separator ',' )USING utf8) as ids from `users_groups_ids` where (object_id={$this->id} and is_user=1) or (object_id={$this->group_id} and is_user=0) ");
				$obj_ids=$this->id;
				if($row=$this->conn->fetch())
					$obj_ids=explode(',',$row->ids);
				$this->permissions_obj=new Selectable($this->conn,'permissions',$this->cache,array('query_where'=>'group by group_id,value_id','object_id'=>$obj_ids));
				$this->permissions_obj->elog=&$this->elog;
			}
			return $this->permissions_obj->getVal($group_name,$field_name,$val_sys);

		}

		public function getCurrent( $user_id = false )  //Авторизация пользователя по сессии, куки или ip
		{
			if( $user_id )
			{
				$this->conn->query('select u.*,g.name as group_name,g.name_sys as group_name_sys from users u inner join groups g on u.group_id=g.id  where u.id='.$user_id);
				if(1==$this->conn->rowCount())
				{
					$row=$this->conn->fetch();
					$user=array();
					foreach($row as $i=>$val)
					{
						if(isset($this->$i))
						{
							$this->$i=$val;//Записываю данные в объект
							$user[$i]=$val;
						}
						else
							$this->add_log("Не используемый параметры в выборке текущего пользователя по id $i=>$val",DEE_NOTICE);
					}
					sessionStart();
					$_SESSION['user']=$user;//Записываю данные в сессию
				}
				else
					$this->add_log('Пользователь не найден по id',DEE_NOTICE);
			}
			elseif (isset($_COOKIE[session_name()])) //Провеяю сессию
			{
				sessionStart();
				if(isset($_SESSION['user']))
				{
					$this->add_log('Авторизация по сессии',DEE_NOTICE);
					$user=$_SESSION['user'];
					if($user)
					foreach($user as $i=>$val)
					{
						if(isset($this->$i))//Выбираю параметры пользователя
							$this->$i=$val;
						else
							$this->add_log("Неиспользуемый параметр в сессии $i=>$val",DEE_NOTICE);
					}
				}
			}
			elseif(isset($_COOKIE['user_id'])&&isset($_COOKIE['user_pass']))//Проверяю пользователя по куки
			{
				$this->conn->query('select u.*,g.name as group_name,g.name_sys as group_name_sys from users u inner join groups g on u.group_id=g.id  where u.email=\''.mysql_escape_string(encode($_COOKIE['user_id'],true)).'\' and u.password=\''.mysql_escape_string(encode($_COOKIE['user_pass'],true)).'\' and g.type=\'users\'');
				if($this->conn->rowCount()==1)
				{
					$row=$this->conn->fetch();
					$user=array();
					foreach($row as $i=>$val)
					{
						if(isset($this->$i))
						{
							$this->$i=$val;//Записываю данные в объект
							$user[$i]=$val;
						}
						else
							$this->add_log("Не используемый параметры в выборке текущего пользователя по куки $i=>$val",DEE_NOTICE);
					}
					sessionStart();
					$_SESSION['user']=$user;//Записываю данные в сессию
				}
				else
					$this->add_log('Пользователь не найден по куки',DEE_NOTICE);
			}
		}

		public function login( $email, $pass, $is_md5 = false )  //Авторизация пользователя по email и паролю
		{
			$this->getEmpty();  //Очищаю класс пользователя

			$email = strtolower( trim( $email ) );
			$pass = trim( $pass );
			if( $email != '' && $pass != '' && preg_match( '#^[\w][-\w\.]*@[\w][-\w]+\.+[a-z]{2,4}$#', $email ) )
			{
				$user = array();
				//Ищу в базе
				$this->conn->query('select u.*,g.name as group_name,g.name_sys as group_name_sys from users u inner join groups g on u.group_id=g.id  where u.email=\''.mysql_escape_string($email).'\' and u.password=\''.mysql_escape_string($is_md5 ? $pass : md5($pass)).'\' and g.type=\'users\'');
				if( $this->conn->rowCount() == 1 )
				{
					$row = $this->conn->fetch();
					foreach( $row as $i => $val )
					{
						if(isset($this->$i))
						{
							$this->$i = $val;  //Записываю данные объект
							if($val)$user[$i] = $val;
						}
						else
							$this->add_log("Не используемый параметр в запросе данных пользователя $i=>$val",DEE_NOTICE);
					}
					$this->conn->query("update users set date_last_visit=now() where id={$row->id};");
				}
				//Ищу в списке главных администраторов
				elseif(isset($GLOBALS['MAIN_ADMIN_USERS'][$email]) && $GLOBALS['MAIN_ADMIN_USERS'][$email]['password']==$pass)
				{
					$user=$GLOBALS['MAIN_ADMIN_USERS'][$email];
					$user['email']=$email;
					$user['the_god_mode']=true;
					foreach($user as $i=>$val)
						if(isset($this->$i))
							$this->$i=$val;
					/*Пологается что админ первый раз авторизировался, сохраняю его в базу*/
					/*Проверяю существует ли группа, если нет, добавляю*/
					$this->conn->query("select id from groups where type='users' and name_sys='{$this->group_name_sys}'");
					$group_id=$this->conn->fetch();
						if(!$group_id)
						{
							$this->group_id=$this->group_id=$this->conn->query("insert into groups (type,name,name_sys) values ('users','{$this->group_name}','{$this->group_name_sys}') ",true);
							$this->conn->query("insert into users_groups_ids(object_id)values({$this->group_id})");
						}
						else
							$this->group_id=$group_id->id;
					/*Добавляю пользователя*/
					if($this->group_id)
					{
						$pass=md5($this->password);
						$this->id=$this->conn->query("insert into users (name,password,email,date_registred,group_id,the_god_mode) values('{$this->name}','$pass','{$this->email}',now(),{$this->group_id},1)");

							$this->conn->query("insert into users_groups_ids(is_user,object_id)values(1,{$this->id})");
					}
				}
				else return 'Пользователя с таким сочетанием email и пароля не существует';
				$this->add_log('Вход произведен');
				sessionStart();
				$this->add_log($user);
				$_SESSION['user']=$user;//Записываю данные в сессию
				setcookie('user_id',encode($email),time()+COOKIE_LOGIN_TIME,'/', $_SERVER['SERVER_NAME']);//В куки
				setcookie('user_pass',encode($user['password']),time()+COOKIE_LOGIN_TIME,'/', $_SERVER['SERVER_NAME']);
				return true;
			}
			return 'Вы ошиблись при вводе email или пароля';
		}

	//Выход пользователя
		public function logout()
		{
			$this->getEmpty();//Очищаю класс пользователя
			setcookie('user_id','',time()+1,'/', $_SERVER['SERVER_NAME']);//В куки
			setcookie('user_pass','',time()+1,'/', $_SERVER['SERVER_NAME']);
			setcookie( 'basket_id' , '' , 9999999999 , '/' );
			if (isset($_COOKIE[session_name()]))
			{
				sessionStart();
				session_destroy();
			}
		}

		public function getData( $name, $user_id = 0 )  // Данные пользователя
		{
			$user_id = $user_id ? $user_id : $this->id;
			if( $this->datas === false )
			{
				$this->datas = array();
				$this->conn->query("SELECT `id`, `prop_name`, `value` FROM `users_datas` WHERE `user_id` = $user_id ORDER BY `prop_name`", false, 'user_data' );
				while( $row = $this->conn->fetch('user_data') )
					$this->datas[$row->prop_name][$row->id] = $row->value;
			}
			if(isset($this->datas[$name]))
				return $this->datas[$name];
			return array();
		}
	}

//Работа с кешем
	class Cache extends Elog_use
	{
		private $conn = false;
		public $load = false;
		private $view = false;
		private $user = false;
		private $loaded_arr = array();

		function Cache( &$conn, &$user, &$view)
		{
			$this->conn = &$conn;
			$this->view = &$view;
			$this->user = &$user;
		}

		function save( $path, $obj )
		{
			if( !USE_CAHCE )

				return true;
			if( empty( $obj ) )
			{
				$this->add_log('Объект не подходит для кеширования',DEE_NOTICE);
				return false;
			}

			$cache = 'cache/data';
			$fPath = "$cache/$path.ch";

			if( file_exists( $fPath ) )
			{
				$this->add_log('Кеш уже сохранен',DEE_NOTICE);
			}

			if( is_dir( $cache ) || mkdir( $cache, CACHE_CHMODE_DIR ) )
			{
				$dirs = explode('/', $path );
				$end = count( $dirs ) - 1;

				foreach( $dirs as $i => $dir )
					if( $i < $end )
					{
						$cache.='/'.$dir;
						if( !is_dir( $cache ) && !mkdir( $cache, CACHE_CHMODE_DIR ) )
						{
							$this->add_log("Ошибка при создании папки $cache",DEE_ERROR);
							return false;
						}
					}

				$file = fopen($fPath, 'w');
				if(!$file)
					return false;
				fwrite($file,serialize($obj));
				fclose($file);
				chmod($fPath,CACHE_CHMODE_FILE);
				$this->add_log("Внесено в кеш $cache",DEE_NOTICE);
			}
			else
			{
				$this->add_log("Ошибка при создании папки $cache",DEE_ERROR);
				return false;
			}
			return true;

		}

		function load( $path )
		{
			//Если не нужен кеш
			//if(!getSConfig('cache'))return false;
			//Если пользователь админ не грузить кеш
			//if($this->user->allowed('mainAccess'))return false;
			$cache="cache/data/$path.ch";
			if(isset($this->loaded_arr[$path]))
			{
				$this->add_log("Из кеша выдано '$cache'",DEE_NOTICE);
				return $this->loaded_arr[$path];
			}
			if(file_exists($cache))
			{
				if(!is_readable($cache))
				{
					$this->add_log("Нет прав на чтение файла '$cache'",DEE_ERROR);
					return false;
				}
				$file = fopen($cache, 'r+');
				if(!$file)
				{
					$this->add_log("Ошибка при чтении файла '$cache'",DEE_ERROR);
					return false;
				}
				$loaded=@unserialize(file_get_contents($cache));
				fclose($file);
				if($loaded)
				{
					$this->add_log("Из кеша загружено '$cache'",DEE_NOTICE);
					$this->loaded_arr[$path]=$loaded;
					return $loaded;
				}
			}
			$this->add_log("Файл кеша отсутсвует '$cache'",DEE_NOTICE);
			return false;
		}

		function delete( $path )
		{
			$fPath = "cache/data/$path.ch";
			$this->add_log( $fPath );
			if( file_exists( $fPath ) )
			{
				if( is_writable( $fPath ) )
					unlink( $fPath );
				else
					$this->add_log("Нет прав на удаление файла кеша '$fPath'",DEE_ERROR);
			}
		}

		function get( $cache_path, $func_file ,$params = false)
		{
			$cache = $this->load( $cache_path );
			if( !$cache )
			{
				$cache_fPath = "cache/functions/$func_file.php";
				if( !file_exists( $cache_fPath ) )
				{
					$this->add_log('Нет файла кешируемой функции',DEE_ERROR);
					return false;
				}
				$user = &$this->user;
				$elog = &$this->elog;
				$conn = &$this->conn;
				$view = &$this->view;
				$load = &$this->load;
				$cache = false;

				include( $cache_fPath );
				$this->save( $cache_path, $cache );
			}
			return $cache;
		}
	}


	class Selectable extends Elog_use  //Класс для выбираемых параметров (настройки , привелегии)
	{
		protected $group_type=false;
		protected $query_where=false;
		protected $cache_array=false;

		protected $conn=false;
		protected $cache=false;
		protected $need_cache=false;
		protected $object_id=false;
		protected $prefix='slbl_';
		protected $table_prefix='selectable';
		protected $text_f='#!text_field#';
		static public $not_text_types=array('select','multiselect','checkbox','radio','multicheckbox');
		static public $arr_types=array('multiselect','multicheckbox');

		function Selectable(&$conn,$group_type,&$cache,$params=array())
		{
			$this->cache=&$cache;
			/*Префикс таблиц*/
			if(isset($params['table_prefix']))
				$this->table_prefix=$params['table_prefix'];

			if(isset($params['need_cache']))
				$this->need_cache=$params['need_cache'];
			$this->object_id=!empty($params['object_id'])?(is_array($params['object_id'])?implode(',',$params['object_id']):$params['object_id']):0;
			$this->query_where= isset($params['query_where'])
				?$params['query_where']
				:'';//'g.type=\''.$group_type.(isset($params['object_id'])?'" and d.object_id=\''.$params['object_id']:'').'\'';
			$this->group_type=$group_type;
			$this->conn=&$conn;
		}

		function getVal($group_name,$field_name,$val_sys=false)
		{

				$cache_user_path='admin/selectable/'.$this->group_type;
				$cache_adm_path=$cache_user_path.'_edit';
			//Если список еще нет то формирую его
			if(!$this->cache_array)
			{
				$cache=false;
				if($this->need_cache)
					$cache=$this->cache->load($cache_user_path);
				if(!$cache)
				{
					/*Гружу системный кеш чтобы сделать упрощенный вариант*/
					$adm_cache=$this->cache->get($cache_adm_path,'edit_selectable',array('group_name'=>$this->prefix.$this->group_type,'table_prefix'=>$this->table_prefix));
					$this->cache_array=array();
					if($adm_cache && !empty($adm_cache['groups']))
					{
						$groups_ids=implode(',',$adm_cache['groups_ids']);
						$datas=array();
						$this->conn->query("select * from {$this->table_prefix}_datas where group_id in ($groups_ids) and object_id in({$this->object_id}) {$this->query_where} order by group_id",false,$this->table_prefix);
						while($data=$this->conn->fetch($this->table_prefix))//Формирую список поле - значения
							$datas[$data->value_text==$this->text_f?$adm_cache['values_index'][$data->value_id]:$data->value_id][]=$data;
						foreach($adm_cache['groups'] as $group)
						{
							$fields=array();
							foreach($group->fields as $field)
								if(isset($datas[$field->id]))
								{
									$values=false;
									/*Текстове поле*/
									if(!in_array($field->type,Selectable::$not_text_types))
										$values=array_shift($datas[$field->id])->value_text;
									/*Поле с несколькими вариантами*/
									elseif(in_array($field->type,Selectable::$arr_types))
									{
										$values=array();
										foreach($datas[$field->id] as $data)
										{
											if(isset($field->values[$data->value_id]))
												$values[]=$field->values[$data->value_id]->value_sys;
										}
									}
									/*поле с одим из варинтов*/
									else
									{
										$v_id=array_shift($datas[$field->id])->value_id;
										if($field->type=='checkbox')
											$values=true;
										elseif(isset($field->values[$v_id]))
											$values=$field->values[$v_id]->value_sys;
									}
									if(!empty($values))
										$fields[$field->name_sys]=$values;

								}
							if(!empty($fields))
								$this->cache_array[$group->name_sys]=$fields;
						}
						/*Сохраняю упрощенный кеш для пользовательской части*/
						 if($this->need_cache)
							$cache=$this->cache->save($cache_user_path,$this->cache_array);
					}
				}
				else $this->cache_array=$cache;

			}
			if(empty($this->cache_array[$group_name]) || !isset($this->cache_array[$group_name][$field_name]))
				return false;

			if($val_sys)//Если нужно проверить наличие значения
			{
				if(is_array($this->cache_array[$group_name][$field_name]))
					return in_array($val_sys,$this->cache_array[$group_name][$field_name]);
				else return isset($this->cache_array[$group_name][$field_name][$val_sys]);
			}
			return $this->cache_array[$group_name][$field_name];
		}
	}


	abstract class Load_use extends Elog_use  //Класс  прототип для загрузки модулей и блоков
	{
		public $params=array();
		public $view;
		public $configs;
		public $conn;
		public $cache;
		protected function getParam( $name, $default_val, $by_isset = false )
		{
			return ( $by_isset ? isset($this->params[$name]) : !empty($this->params[$name])) ? $this->params[$name] : $default_val;
		}
	}


	class Load extends Elog_use  //Класс для работы с блоками
	{
	//Хранилище прототипов
		private $loaded_blocks=array();
		private $loaded_modules=array();
		private $conn=false;
		private $configs=false;
		private $cache=false;
		private $view=false;
		private $user=false;
		private $mode='site';
	//Инициализация
		function Load(&$conn,&$user,&$view,&$cache,&$configs)
		{
			$this->mode=site_mode;
			$this->conn=&$conn;
			$this->configs=&$configs;
			$this->view=&$view;
			$this->cache=&$cache;
			$this->user=&$user;
		}

		private function getLoad($mess_ok,$mess_err,&$arr,$name,$path)
		{
			if( !isset( $arr[$name] ) )//Чтобы загрузить класс только один раз
			{
				//Если файл класса существует
				if(file_exists($path))
				{
					include($path);
					//Инициализирую объект класса
					$arr[$name]=new $name();
					//Передаю основной объект страницы
					$arr[$name]->view=&$this->view;
					$arr[$name]->configs=&$this->configs;
					$arr[$name]->user=&$this->user;
					$arr[$name]->conn=&$this->conn;
					$arr[$name]->cache=&$this->cache;
					$arr[$name]->elog=&$this->elog;
					$arr[$name]->load=&$this;
					$this->add_log($mess_ok,DEE_NOTICE);
					return true;
				}
				$this->add_log($mess_err,DEE_ERROR);
				return false;
			}
			return true;

		}
	//Сгенерировать блок
		function block( $name, $params = array(), $block_dir = false )
		{
			if(!$block_dir)
				$block_dir = $this->mode;

			$cache_this_block = false;

				// Блоки которые нужно кэшировать
			$block_list_cache = array(	'navi_top',
										'menu_left',
										'menu_top',
										'store_product_cat_links',
										'footer_navi',
										'preview_akcion_and_news',
										'news_hits_sales_product_list',
										'preview_akcion_and_news_widget', );

 				// Выдаем кеш блока
			if( USE_CAHCE && in_array( $name, $block_list_cache ) )
			{
				$new_name = ( $name == 'store_product_cat_links' ) ? $name.'_'.$this->view->url : $name;

				$path = PATH_TO_CACHE_DIR.$new_name.'.html';
				if( is_file( ADMIN_PATH.$path ) )
				{
					if( $html = file_get_contents( $path ) )
					{
						$difference = (int)( ( time() - filemtime( $path ) ) / 60 );
						if( $difference < CAHCE_MINUTES )
							return $html;
					}
				}
				$cache_this_block = true;
			}

			if(!$this->getLoad(
				"Загружен блок $name",
				"Отсутствует файл блока $name",
				$this->loaded_blocks,
				$name,
				"templ/{$block_dir}/blocks/$name.php")
			)
				return '';

				// Передаю параметры
			$this->loaded_blocks[$name]->params = $params;
				// Загружаю блок
			$html = $this->loaded_blocks[$name]->getBlock();

			if( $cache_this_block )  // Кеширую блок если нужно
				file_put_contents( $path, $html );

			return $html;
		}
	//Выполнить дейсвие
		function module($name,$action,$params=array())
		{
			if(! $this->getLoad(
			"Загружен модуль $name",
			"Отсутствует файл модуля $name",
			$this->loaded_modules,
			$name,
			"modules/$name.php"))
				return false;
			//Передаю параметры
			$this->loaded_modules[$name]->params=$params;
			return $this->loaded_modules[$name]->$action();

		}
	//Загрузка шаблона
		function templ($templ=false)
		{
			if(!$templ)$templ=$this->view->templ;
			$path="templ/{$this->mode}/$templ.php";
			if(file_exists($path))
			{
				$user=&$this->user;
				$configs=&$this->configs;
				$elog=&$this->elog;
				$conn=&$this->conn;
				$view=&$this->view;
				$cache=&$this->cache;
				$load=&$this;
				include($path);
				return true;
			}
			return false;
		}
	}
	